#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>

#define DEFAULT_PORT 7000
#define MULTICAST_ADDRESS "239.255.255.250"

uv_udp_t recv_socket;

void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
  buf->base = (char *)malloc(suggested_size);
  buf->len = suggested_size;
}

void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, uint32_t flags) {
  if (nread < 0) {
    fprintf(stderr, "Read error %s\n", uv_err_name(nread));
    uv_close((uv_handle_t *)req, NULL);
    free(buf->base);
    return;
  }

  if (nread == 0)
  {
    fprintf(stderr, "Read error %s\n", uv_err_name(nread));
    free(buf->base);
    return;
  }

  char sender[17] = {0};
  uv_ip4_name((const struct sockaddr_in *)addr, sender, 16);

  fprintf(stderr, "Recv from %s\n", sender);

  // echo to stdout
  printf("%s\n", buf->base);

  free(buf->base);
}

struct A
{
  int a = 2;
};

struct B
{
  int a = 3;
};

struct C : public A, B
{
  int c = 4;
};

int main() {
  C c;

  A* a = &c;

  B* b = &c;

  uv_loop_t *loop = uv_default_loop();

  uv_udp_init(loop, &recv_socket);

  struct sockaddr_in recv_addr;
  uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &recv_addr);
  uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);

  struct sockaddr_in multicast_addr;
  uv_ip4_addr(MULTICAST_ADDRESS, DEFAULT_PORT, &multicast_addr);
  uv_udp_set_membership(&recv_socket, MULTICAST_ADDRESS, "0.0.0.0", UV_JOIN_GROUP);

  uv_udp_recv_start(&recv_socket, alloc_buffer, on_read);

  return uv_run(loop, UV_RUN_DEFAULT);
}
